package cn.yunyichina.scheduler.jobs.service.register.impl;

import cn.yunyichina.provider.framework.dubbo.service.BaseService;
import cn.yunyichina.provider.framework.dubbo.service.RegisterService;
import cn.yunyichina.provider.iface.entity.base.HospitalOutVo;
import cn.yunyichina.provider.iface.entity.base.OrderExtVo;
import cn.yunyichina.provider.iface.entity.base.Rule;
import cn.yunyichina.provider.iface.entity.common.Response;
import cn.yunyichina.scheduler.jobs.service.register.RegisterStopService;
import cn.yunyichina.scheduler.jobs.service.register.callable.StopRegisterCall;
import cn.yunyichina.scheduler.jobs.thread.pool.SimpleThreadFactory;
import cn.yunyichina.utils.commons.DateUtils;
import cn.yunyichina.utils.convert.JsonUtils;
import com.alibaba.fastjson.JSON;
import org.apache.commons.collections.map.HashedMap;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.FutureTask;
import java.util.concurrent.TimeUnit;

/**
 * 挂号停诊轮询定时器
 * Created by Administrator on 2017/5/19.
 */
@Service
public class RegisterStopServiceImpl implements RegisterStopService{
    private static final Logger logger = LoggerFactory.getLogger(RegisterStopServiceImpl.class);

    @Override
    public void doExecute() {
        //查询缓存中所有的医院
        Response hospitalResp =  BaseService.callUnderlineFromInternal("yyt.base.hospital.by.app.code.list","{\"app_code\":\"all\"}");
        if (!"0".equals(hospitalResp.getResultCode())) {
            logger.error("doExecute, 查询缓存医院失败app_code=all");
            return ;
        }
        List<HospitalOutVo> hospitalOutVoList = JsonUtils.parseArray(hospitalResp.getResult(),HospitalOutVo.class);

        int threadNum = 5;//默认的线程数
        // 设置线程池的数量
        ExecutorService collectExec = Executors.newFixedThreadPool(threadNum, new SimpleThreadFactory("registerStop"));

        List<FutureTask<List<OrderExtVo>>> taskList = new ArrayList<FutureTask<List<OrderExtVo>>>();

        for(HospitalOutVo hospital:hospitalOutVoList) {
            String orgCode = hospital.getHospitalCode();

            Map<String,String> map = new HashedMap();
            map.put("attribute_name" , "acceptStopRegType");
            map.put("org_code" , orgCode);
            Response ruleResp = BaseService.callHumpFromInternal("yyt.base.rule.select", JSON.toJSONString(map));//RegisterService.callUnderlineFromInternal("yyt.register.reg.cache.rule.get","{\"org_code\":\""+ orgCode +"\"}");
            if (!"0".equals(ruleResp.getResultCode())) {
                logger.error("doExecute, 查询缓存规则失败：" + orgCode );
                continue;
            }
            Rule rule=JsonUtils.parseObject(ruleResp.getResult(), Rule.class);
            String acceptStopRegType = "";//1:医院HIS主动推送 2:定时轮询
            if(rule != null){
                acceptStopRegType = rule.getAttributeProperties();//单位：分钟
            }

            if("2".equals(acceptStopRegType)){
                StopRegisterCall call = new StopRegisterCall(orgCode,"");
                // 创建每条指令的采集任务对象
                FutureTask<List<OrderExtVo>> collectTask = new FutureTask<List<OrderExtVo>>(call);
                // 添加到list,方便后面取得结果
                taskList.add(collectTask);
                // 提交给线程池 exec.submit(task);
                collectExec.submit(collectTask);
            }
        }

        // 阻塞主线程,等待采集所有子线程结束,获取所有子线程的执行结果,get方法阻塞主线程,再继续执行主线程逻辑
        try {
            for (FutureTask<List<OrderExtVo>> taskF : taskList) {
                // 防止某个子线程查询时间过长 超过默认时间没有拿到抛出异常
                List<OrderExtVo> collectData = taskF.get(Long.MAX_VALUE, TimeUnit.DAYS);
                if (!CollectionUtils.isEmpty(collectData) && logger.isInfoEnabled()) {
                    logger.info("date:{} RegisterStopServiceImpl success，size={}", new Object[] {DateUtils.getDatetime(),collectData.size() });
                }
            }

        } catch (Exception e) {
            e.printStackTrace();
        }
        // 处理完毕,关闭线程池,这个不能在获取子线程结果之前关闭,因为如果线程多的话,执行中的可能被打断
        collectExec.shutdown();
    }
}
